package com.iris.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.text.NumberFormat;
import java.util.Arrays;

import org.apache.commons.io.IOUtils;
import org.apache.tools.zip.ZipOutputStream;

/**
 * 文件处理工具类
 */
public class FilesUtil {

	public static final int FLUSH_BUFFER_SIZE = 10240; // buffer size=10K

	/**
	 * 获取文件类型描述
	 */
	public static String getFileType(java.io.File file) {
		if (file == null) {
			return "";
		}
		if (file.isDirectory()) {
			return "文件夹";
		}
		String ext = getFileExt(file.getName());
		return FileType.getFileType(ext);
	}

	/**
	 * 取文件扩展名
	 */
	public static String getFileExt(String clientFileName) {
		if (clientFileName == null || clientFileName.equals("")) {
			return "";
		}
		String[] arrFile = clientFileName.split("\\x2E"); // "\\x2E" == "."
		return arrFile[arrFile.length - 1];
	}

	/**
	 * 获取短文件名
	 */
	public static String getShortFileName(String fileName) {
		if (fileName == null || fileName.equals("")) {
			return "";
		}
		int index = indexOfLastSeparator(fileName);
		return fileName.substring(index + 1);
	}

	public static int indexOfLastSeparator(String filename) {
		if (filename == null) {
			return -1;
		} else {
			int lastUnixPos = filename.lastIndexOf('/');
			int lastWindowsPos = filename.lastIndexOf('\\');
			return Math.max(lastUnixPos, lastWindowsPos);
		}
	}

	/**
	 * 获取文件的大小
	 */
	public static String getFileSize(long filesize) {
		double size = filesize * 1.0d;
		NumberFormat nf = NumberFormat.getInstance();
		nf.setMaximumFractionDigits(2);
		nf.setMinimumFractionDigits(0);

		double sizeGB = size / 1024 / 1024 / 1024;
		if (sizeGB >= 1) {
			return nf.format(sizeGB) + " GB";
		}

		double sizeMB = size / 1024 / 1024;
		if (sizeMB >= 1) {
			return nf.format(sizeMB) + " MB";
		}

		double sizeKB = size / 1024;
		if (sizeKB >= 1) {
			return nf.format(sizeKB) + " KB";
		}
		return filesize + " bytes";
	}

	/**
	 * 获取文件的大小
	 */
	public static String getFileSize(File file) {
		return getFileSize(file.length());
	}

	/**
	 * 拷贝文件从目录source到目录target，包括文件名selectedFileNames中的文件
	 * 
	 * @throws IOException
	 */
	public static void copyFile(File source, File target, String[] fileNames) throws IOException {
		Arrays.sort(fileNames);
		File[] files = source.listFiles();
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			if (Arrays.binarySearch(fileNames, f.getName()) >= 0) {
				FileInputStream in = new FileInputStream(f);
				File t = new File(target.getAbsolutePath() + File.separator + f.getName());
				FileOutputStream out = new FileOutputStream(t);
				int c = -1;
				int buffsize = 0;
				while ((c = in.read()) != -1) {
					out.write(c);
					if (buffsize++ == FLUSH_BUFFER_SIZE) {
						out.flush();
						buffsize = 0;
					}
				}
				out.flush();
				out.close();
				in.close();
			}
		}
	}

	/**
	 * 拷贝文件
	 * 
	 * @param srcFile
	 *            源文件
	 * @param destFile
	 *            目标文件
	 * @throws IOException
	 *             IO异常
	 */
	public static void copyFile(File srcFile, File destFile) throws IOException {
		copyFile(srcFile, destFile, true);
	}

	/**
	 * 拷贝文件
	 * 
	 * @param srcFile
	 *            源文件
	 * @param destFile
	 *            目标文件
	 * @param preserveFileDate
	 *            是否保持时间戳
	 * @throws IOException
	 *             IO异常
	 */
	public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
		if (srcFile == null) {
			throw new NullPointerException("Source must not be null");
		}
		if (destFile == null) {
			throw new NullPointerException("Destination must not be null");
		}
		if (!srcFile.exists()) {
			throw new IOException("Source '" + srcFile + "' does not exist");
		}
		if (srcFile.isDirectory()) {
			throw new IOException("Source '" + srcFile + "' exists but is a directory");
		}
		if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
			throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
		}
		if (destFile.getParentFile() != null && !destFile.getParentFile().exists()
				&& !destFile.getParentFile().mkdirs()) {
			throw new IOException("Destination '" + destFile + "' directory cannot be created");
		}
		if (destFile.exists() && !destFile.canWrite()) {
			throw new IOException("Destination '" + destFile + "' exists but is read-only");
		} else {
			doCopyFile(srcFile, destFile, preserveFileDate);
		}
	}

	// 拷贝文件
	private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
		if (destFile.exists() && destFile.isDirectory()) {
			throw new IOException("Destination '" + destFile + "' exists but is a directory");
		}
		FileInputStream input = new FileInputStream(srcFile);
		try {
			FileOutputStream output = new FileOutputStream(destFile);
			try {
				IOUtils.copy(input, output);
			} finally {
				IOUtils.closeQuietly(output);
			}
		} finally {
			IOUtils.closeQuietly(input);
		}
		if (srcFile.length() != destFile.length()) {
			throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
		}
		if (preserveFileDate) {
			destFile.setLastModified(srcFile.lastModified());
		}
	}

	/**
	 * 默认方式清理指定目录下的文件：文件时间超过24小时者删除
	 * 
	 * @param directory
	 */
	public static void defaultClean(File directory) {
		if (!directory.exists()) {
			return;
		}
		long limit = 24 * 60 * 60 * 1000L; // 最大时限24小时
		File[] files = directory.listFiles();
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			long time = System.currentTimeMillis() - f.lastModified() - limit;
			if (time >= 0) {
				if (f.isDirectory()) {
					defaultClean(f);
				}
				f.delete();
			}
		}
	}

	/**
	 * 删除目录下的超过时限的文件（不含目录）,并且文件的后缀为fileExt中的一个
	 * 
	 * @param directory
	 * @param andSubFolder
	 *            是否删除子目录下的文件
	 * @param fileExt
	 *            如"txt,exe,xls"
	 * @throws IOException
	 */
	public static void cleanDir(File directory, boolean andSubFolder, String fileExt) {
		long limit = 24 * 60 * 60 * 1000L; // 最大时限24小时
		String fileext = fileExt.toLowerCase();
		File[] files = directory.listFiles();
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			long time = System.currentTimeMillis() - f.lastModified() - limit;
			if (time >= 0) {
				if (f.isDirectory() && andSubFolder) {
					cleanDir(f, andSubFolder, fileext);
				}
				String ext = getFileExt(f.getName()).toLowerCase();
				if (f.isFile() && !"".equals(ext) && fileext.indexOf(ext) >= 0) {
					f.delete();
				}
			}
		}
	}

	/**
	 * 判断目录及其子目录下是否有文件
	 * 
	 * @param directory
	 * @throws IOException
	 */
	public static boolean containFiles(File directory) throws IOException {
		if (directory == null || !directory.exists()) {
			return false;
		}
		File[] files = directory.listFiles();
		for (int i = 0; i < files.length; i++) {
			File f = files[i];
			if (f.isFile()) {
				return true;
			}
			if (f.isDirectory()) {
				return containFiles(f);
			}
		}
		return false;
	}

	/**
	 * 删除目录下的所有文件或目录
	 * 
	 * @param directory
	 *            需要删除的目录
	 * @throws IOException
	 *             删除操作异常
	 */
	public static void deleteFiles(File directory) throws IOException {
		File[] files = directory.listFiles();
		for (int i = 0; files != null && i < files.length; i++) {
			File f = files[i];
			if (f.isDirectory()) {
				deleteFiles(f);
			}
			f.delete();
		}
		directory.delete();
	}

	/**
	 * 删除目录下的所有文件
	 * 
	 * @param directory
	 *            需要删除文件所属的目录
	 * @throws IOException
	 *             删除操作异常
	 */
	public static void cleanFiles(File directory) throws IOException {
		File[] files = directory.listFiles();
		for (int i = 0; files != null && i < files.length; i++) {
			File f = files[i];
			if (f.isDirectory()) {
				deleteFiles(f);
			}
			f.delete();
		}
	}
	
	/**
	 * 删除绝对路径文件
	 * 
	 * @param directory
	 *            需要删除文件所属的目录
	 * @throws IOException
	 *             删除操作异常
	 */
	public static void deleteFile(File file) throws IOException {
		if(file.isFile()){
			file.delete();
		}
	}

	/**
	 * 删除目录下所有文件（不含目录）,并且文件的后缀为fileExt中的一个
	 * 
	 * @param directory
	 *            需要删除的目录
	 * @param alsoSubFolder
	 *            是否删除子目录下的文件
	 * @param fileExt
	 *            文件后缀，用逗号分割，如"txt,exe,xls"
	 * @throws IOException
	 *             删除操作异常
	 */
	public static void deleteFiles(File directory, boolean alsoSubFolder, String fileExt) throws IOException {
		String fileext = fileExt.toLowerCase();
		File[] files = directory.listFiles();
		for (int i = 0; files != null && i < files.length; i++) {
			File f = files[i];
			if (f.isDirectory() && alsoSubFolder) {
				deleteFiles(f, alsoSubFolder, fileext);
			}
			String ext = getFileExt(f.getName()).toLowerCase();
			if (f.isFile() && !"".equals(ext) && fileext.indexOf(ext) >= 0) {
				f.delete();
			}
		}
	}

	/**
	 * 创建一个指定编码的文件Writer
	 * 
	 * @param out
	 *            输出
	 * @param enc
	 *            编码
	 * @return Writer
	 * @throws UnsupportedEncodingException
	 *             不支持的编码
	 */
	public static Writer makeWriter(OutputStream out, String enc) throws UnsupportedEncodingException {
		if ("UTF-8".equals(enc)) {
			enc = "UTF8";
		}
		Writer writer = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(out), enc));
		return writer;
	}

	/**
	 * 创建一个指定编码的文件Reader
	 * 
	 * @param in
	 *            输入
	 * @param enc
	 *            编码
	 * @return Reader
	 * @throws UnsupportedEncodingException
	 *             不支持的编码
	 */
	public static Reader makeReader(InputStream in, String enc) throws UnsupportedEncodingException {
		if ("UTF-8".equals(enc)) {
			enc = "UTF8";
		}
		Reader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(in), enc));
		return reader;
	}

	/**
	 * 创建整个目录
	 * 
	 * @param path
	 *            目录路径
	 * @return 目录存在否
	 */
	public static boolean createDir(String path) {
		File file = new File(path);
		return file.exists() ? true : file.mkdirs();
	}

	/**
	 * 
	 * @param inputFileName
	 *            输入一个文件夹
	 * @param zipFileName
	 *            输出一个压缩文件夹，打包后文件名字
	 * @throws Exception
	 */
	public static void zip(String inputFileName, String zipFileName) throws Exception {
		zip(zipFileName, new File(inputFileName));
	}

	private static void zip(String zipFileName, File inputFile) throws Exception {
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
		zip(out, inputFile, "");
		out.close();
	}

	private static void zip(ZipOutputStream out, File f, String base) throws Exception {
		if (f.isDirectory()) { // 判断是否为目录
			File[] fl = f.listFiles();
			out.putNextEntry(new org.apache.tools.zip.ZipEntry(base + "/"));
			base = base.length() == 0 ? "" : base + "/";
			for (int i = 0; i < fl.length; i++) {
				zip(out, fl[i], base + fl[i].getName());
			}
		} else { // 压缩目录中的所有文件
			out.putNextEntry(new org.apache.tools.zip.ZipEntry(base));
			FileInputStream in = new FileInputStream(f);
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}
			in.close();
		}
	}
	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * @param   sPath 被删除目录的文件路径
	 * @return  目录删除成功返回true，否则返回false
	 */
	private static boolean deleteDirectory(String sPath) {
		//如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		//如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		boolean flag = true;
		//删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			//删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag)
					break;
			} //删除子目录
			else {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
		}
		if (!flag)
			return false;
		//删除当前目录
		if (dirFile.delete()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 删除单个文件
	 * @param   sPath    被删除文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	private static boolean deleteFile(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.isFile() && file.exists()) {
			file.delete();
			flag = true;
		}
		return flag;
	}

	/**
	 *  根据路径删除指定的目录或文件，无论存在与否
	 *@param sPath  要删除的目录或文件
	 *@return 删除成功返回 true，否则返回 false。
	 */
	public static boolean DeleteFolder(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 判断目录或文件是否存在
		if (!file.exists()) { // 不存在返回 false
			return flag;
		} else {
			// 判断是否为文件
			if (file.isFile()) { // 为文件时调用删除文件方法
				return deleteFile(sPath);
			} else { // 为目录时调用删除目录方法
				return deleteDirectory(sPath);
			}
		}
	}
	
	/**
	 * 说明 : 字符串内容创建文件
	 * 2015-7-31
	 * @author ex_kjkfb_xiaozs
	 * @param path
	 * @param content
	 * @return
	 * @throws IOException 
	 */
	public static String createFile(String path,String filename,String content) throws IOException{
		createDir(path);
		String filePath=path;
		if(filePath.endsWith("/")){
			filePath+=filename;
		}else{
			filePath+="/"+filename;
		}
		File file=new File(filePath);
		if(file.exists()){
			deleteFile(file);
		}
		FileWriter writer=new FileWriter(file);
		writer.write(content);
		writer.close();
		return filePath;
	}
	
	public static String createFile(String path,String filename,InputStream input) throws IOException{
		createDir(path);
		String filePath=path;
		if(filePath.endsWith("/")){
			filePath+=filename;
		}else{
			filePath+="/"+filename;
		}
		File file=new File(filePath);
		if(file.exists()){
			deleteFile(file);
		}
		FileOutputStream out=new FileOutputStream(file);
		byte[] buffer = new byte[1024]; 
		int offset = -1; 
		while((offset = input.read(buffer)) != -1) { 
			out.write(buffer, 0, offset); 
		} 
		input.close();
		out.close();
		return filePath;
	}
	
	public static void main(String[] args) {
		try {
//			File file = new File("C:\\Users\\victor\\Desktop\\meta\\msq_schemata_201606223404");
//			FileInputStream input = new FileInputStream(file);
//			byte[] b=new byte[1];
//			while(input.read(b)>-0){
//				for (byte c : b) {
//					System.out.print(c+",");
//				}
//			}
//			input.close();
			String str = new String(new byte[]{13});
			String strn = new String(new byte[]{10});
			String test="sdfdsf\nggggg"+str+"ffff"+strn+"==="+strn;
			System.out.println(test.endsWith("\n"));
//			System.out.println(test);
//			System.out.print(test.replace("\r\n", ","));
//			System.out.println("\n".getBytes()[0]);
//			System.out.println("\r".getBytes()[0]);
		} catch ( Exception e) {
			e.printStackTrace();
		}
	}
	
}
